﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace XFFSM
{
    public class StateNodeLayer : GraphLayer
    {

        #region 字段

        private StateStyles stateStyles;
        private Vector2 startPos;
        private bool isSelectNodes = false;
        private Rect selectRect;
        private GUIStyle selectStyle = new GUIStyle("SelectionRect");
        private bool isDragNode = false;

        private Rect stateRunningRect;
        private GUIStyle stateRunningStyleBg = new GUIStyle("MeLivePlayBackground");
        private GUIStyle stateRunningStyle = new GUIStyle("MeLivePlayBar");
        private float widthScale = 0;

        #endregion

        public StateNodeLayer(FSMEditorWindow editorWindow) : base(editorWindow) {
            stateStyles = new StateStyles();
        }

        #region 重写方法
        public override void OnGUI(Rect rect)
        {
            base.OnGUI(rect);

            if (Context.Instance.RuntimeFSMController == null) return;

            stateStyles.ApplyZoomFactor(Context.Instance.ZoomFactor);

            for (int i = 0; i < Context.Instance.RuntimeFSMController.states.Count; i++)
            {
                DrawNode(Context.Instance.RuntimeFSMController.states[i]);
            }


            DrawSelectBox();
            rect.Set(rect.x, rect.y + rect.height - 15, rect.width, 15);
            EditorGUI.DrawRect(rect,ColorConst.ParaBackground);
            GUILayout.BeginArea(rect);
            GUILayout.BeginHorizontal();
            if(Context.Instance.FSMController != null)
                GUILayout.Label(Context.Instance.FSMController.name);
            GUILayout.FlexibleSpace(); 
            GUILayout.Label(AssetDatabase.GetAssetPath(Context.Instance.RuntimeFSMController));
            GUILayout.EndHorizontal();
            GUILayout.EndArea();
            //Handles.color = Color.gray; 
            //Handles.DrawLine(new Vector2(rect.x, rect.y), new Vector2(rect.x + rect.width, rect.y));
        }

        public override void ProcessEvents()
        {
            base.ProcessEvents();

            if (Context.Instance.RuntimeFSMController == null) return;

            Context.Instance.hoverState = null;

            for (int i = Context.Instance.RuntimeFSMController.states.Count - 1; i>=0; i--)
            {
                CheckNodeClick(Context.Instance.RuntimeFSMController.states[i]);
            }

            // 鼠标左键按下事件
            if (Event.current.type == EventType.MouseDown && Event.current.button == 0) {
                startPos = Event.current.mousePosition;
                isSelectNodes = true;
            }

            // 鼠标左键抬起事件
            if (Event.current.type == EventType.MouseUp && Event.current.button == 0) {
                isSelectNodes = false;
            }

            if (Event.current.type == EventType.MouseLeaveWindow && Event.current.button == 0) {
                isSelectNodes = false;
                isDragNode = false;
            }

            if (Event.current.type == EventType.MouseDrag && Event.current.button == 0 && !isSelectNodes&&isDragNode) 
            {
                foreach (var item in Context.Instance.SelectNodes)
                {
                    item.rect.center += Event.current.delta / Context.Instance.ZoomFactor;
                    EditorUtility.SetDirty(Context.Instance.RuntimeFSMController);
                }
            }

            // 监听鼠标右键抬起事件
            if (Event.current.type == EventType.MouseUp && Event.current.button == 1) {
                foreach (var item in Context.Instance.RuntimeFSMController.states)
                {
                    if (GetTransformedRect(item.rect).Contains(Event.current.mousePosition)) {

                        // 停止预览
                        Context.Instance.StopPreviewTransition();

                        // 显示菜单选项 
                        ShowMenu(item);
                        
                        Event.current.Use();
                        break;
                    }
                }
            }

        }

        public override void Update()
        {
            base.Update();
            
            if (Application.isPlaying && Context.Instance.FSMController != null )
            {
                int index = Context.Instance.FSMController.RuntimeFSMController.IndexOf(Context.Instance.RuntimeFSMController);
                if (Context.Instance.FSMController.GetCurrentStateInfo(index) != null) 
                {                     
                    widthScale += Time.deltaTime;
                    widthScale %= 1;
                } 
            } 
        }

        #endregion


        #region 方法

        private void DrawNode(FSMStateNodeData node) {

            Rect rect = GetTransformedRect( node.rect);

            if (position.Overlaps(rect)) { 
                GUI.Box(rect, node.name, GetStateStyle(node));

                if (Context.Instance.FSMController != null && Application.isPlaying )
                {
                    int index = Context.Instance.FSMController.RuntimeFSMController.IndexOf(Context.Instance.RuntimeFSMController);
                    FSMStateNode stateNode = Context.Instance.FSMController.GetCurrentStateInfo(index);

                    if (stateNode != null && node.name.Equals(stateNode.data.name)) 
                    {
                        float offset = Context.Instance.ZoomFactor * 3;
                        stateRunningRect.Set(rect.x + offset, rect.y + rect.height / 4 * 3 + offset, rect.width - offset * 2, rect.height / 4 - offset*2);

                        stateRunningStyle.fixedHeight = stateRunningRect.height;
                        stateRunningStyleBg.fixedHeight = stateRunningRect.height;

                        GUI.Box(stateRunningRect,string.Empty,stateRunningStyleBg);
                        stateRunningRect.width *= widthScale;
                        GUI.Box(stateRunningRect, string.Empty, stateRunningStyle);
                    }
                    
                }

            }
        }

        private GUIStyle GetStateStyle(FSMStateNodeData node)
        {
            bool isSelected = Context.Instance.SelectNodes.Contains(node);

            int index = -1;
            FSMStateNode stateNode = null;
            if (Context.Instance.FSMController != null) {
                index = Context.Instance.FSMController.RuntimeFSMController.IndexOf(Context.Instance.RuntimeFSMController);
                stateNode = Context.Instance.FSMController.GetCurrentStateInfo(index);
            }

            if ( Application.isPlaying && Context.Instance.FSMController != null
                && stateNode != null && node.name.Equals(stateNode.data.name)
                && Context.Instance.FSMController.RuntimeFSMController.Contains(Context.Instance.RuntimeFSMController)) 
            {
                // 当前正在执行的状态 
                return this.stateStyles.Get(isSelected ? Style.OrangeOn : Style.Orange);
            }else if (Application.isPlaying == false && node.defaultState)
            {
                return this.stateStyles.Get(isSelected ? Style.OrangeOn : Style.Orange);
            }
            else if (node.name == FSMConst.entryState)
            {
                return this.stateStyles.Get(isSelected ? Style.GreenOn : Style.Green);
            }
            else if (node.name == FSMConst.anyState)
            {
                return this.stateStyles.Get(isSelected ? Style.MintOn : Style.Mint);
            }
            else {
                return this.stateStyles.Get(isSelected ? Style.NormalOn : Style.Normal);
            }

        }

        private void CheckNodeClick(FSMStateNodeData node) {

            Rect rect = GetTransformedRect(node.rect);
            if ( position.Overlaps(rect) && rect.Contains(Event.current.mousePosition) ) {

                Context.Instance.hoverState = node;

                if (Event.current.type == EventType.MouseDown && (Event.current.button == 0 || Event.current.button == 1)) {

                    if (!Context.Instance.SelectNodes.Contains(node))
                    {
                        Context.Instance.SelectNodes.Clear();
                        Context.Instance.SelectNodes.Add(node);
                    }

                    if (Event.current.button == 0) {
                        isDragNode = true;

                        OnNodeClick(node);

                    }

                    FSMStateInspectorHelper.Instance.Inspect(Context.Instance.RuntimeFSMController, node);

                    Event.current.Use();
                }

               
            }


        }

        public void OnNodeClick(FSMStateNodeData node) {

            if (Context.Instance.isPreviewTransition ) {

                //Debug.LogFormat("添加过渡: from : {0} to : {1} ",this.Context.fromState.name,this.Context.hoverState.name);

                FSMTransitionFactory.CreateTransition(Context.Instance.RuntimeFSMController, Context.Instance.fromState.name, node.name);

                // 添加过渡 
                Context.Instance.StopPreviewTransition();
            }

            Context.Instance.selectTransition = null;

        }

        private void DrawSelectBox() {

            if (isSelectNodes == false) { selectRect = Rect.zero; return; }

            Vector2 detal = Event.current.mousePosition - startPos;

            selectRect.center = startPos + detal * 0.5f;
            selectRect.width = Mathf.Abs( detal.x);
            selectRect.height = Mathf.Abs( detal.y);

            GUI.Box(selectRect, string.Empty, selectStyle);

            Context.Instance.SelectNodes.Clear();

            foreach (var item in Context.Instance.RuntimeFSMController.states)
            {
                CheckSelectNode(item);
            }

        }

        private void CheckSelectNode(FSMStateNodeData node) {
            if (GetTransformedRect(node.rect).Overlaps(selectRect,true)) {
                Context.Instance.SelectNodes.Add(node);
            }
        }

        private void ShowMenu(FSMStateNodeData node) {

            var genricMenu = new GenericMenu();
            bool is_any = node.name.Equals(FSMConst.anyState);
            bool is_entry = node.name.Equals(FSMConst.entryState);

            if (!is_entry)
            {
                genricMenu.AddItem(new GUIContent("Make Transition"), false, () =>
                {
                    Context.Instance.StartPreviewTransition(node);
                });
            }
            else {
                genricMenu.AddItem(new GUIContent("Make Transition"), false, null);
            }

            if ( !is_entry && !is_any ) {
                genricMenu.AddItem(new GUIContent("Set as Layer Default State"), false, () =>
                {
                    // TODO 
                    SetDefaultState(node);
                });
                genricMenu.AddItem(new GUIContent("Delete"), false, () =>
                {
                    DeleteStates();
                });
            }

            genricMenu.ShowAsContext();  
        }

        private void DeleteStates() {

            foreach (var item in Context.Instance.SelectNodes)
            {
                FSMStateNodeFactory.DeleteState(Context.Instance.RuntimeFSMController,item);
            }
            Context.Instance.SelectNodes.Clear();
            AssetDatabase.SaveAssets();
        }

        private void SetDefaultState(FSMStateNodeData node) {
            foreach (var item in Context.Instance.RuntimeFSMController.states)
            {
                item.defaultState = false;
            }
            node.defaultState = true;
            Context.Instance.RuntimeFSMController.Save();
        }

        #endregion 



    }

}

